package vg.modules.conveyor;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;

import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.filechooser.FileFilter;

import ru.nsu.fit.iconveyor.conveyor.Globals;
import ru.nsu.fit.iconveyor.conveyor.node.Node;

import ru.nsu.fit.iconveyor.conveyor.storage.Utils;
import ru.nsu.fit.iconveyor.conveyor.utils.jar.JarClassLoader;
import vg.modules.opener.CommandOpener;
import vg.services.data_base_manager.data.graph.Attribute;
import vg.services.data_base_manager.data.graph.Graph;
import vg.services.data_base_manager.data.graph.Vertex;
import vg.services.data_base_manager.data.header.GraphModelHeader;
import vg.services.main_manager.MainManager;
import vg.services.plugin_manager.event_and_request.event.UIEventOpenNewGraph;
import vg.services.plugin_manager.interfaces.IPlugin;
import vg.services.plugin_manager.realization.PluginParameter;
import vg.services.user_interface_manager.interfaces.AMenuItem;
import vg.shared.zip.Unzip;

public class ImporterPlugin implements IPlugin {
	// Defines
	public static final String DEF_LAST_ICONVEYOR_IMPORT_DIRECTORY = "DEF_LAST_ICONVEYOR_IMPORT_DIRECTORY";
	
	// Main data
	private final ConveyorPlugin conveyorPlugin;

	public ImporterPlugin(ConveyorPlugin conveyorPlugin) {
		this.conveyorPlugin = conveyorPlugin;
	}
	
	@Override
	public void install(final PluginParameter pluginParameter) throws Exception {
		// initialize components
		JMenuItem importIConveyorMenuItem = new JMenuItem("Import to IConveyor"); 

		// initialize listeners
		importIConveyorMenuItem.addActionListener(new ActionListener() {		
			public void actionPerformed(ActionEvent e) {
				final JFileChooser fileChooser = new JFileChooser(".");
				String lastDir = MainManager.config.getProperty(DEF_LAST_ICONVEYOR_IMPORT_DIRECTORY);
				if(lastDir != null) {
					fileChooser.setCurrentDirectory(new File(lastDir));
				}
				
		       	fileChooser.addChoosableFileFilter(new FileFilter() {
					public String getDescription() {				
						return Globals.CONVEYOR_FILE_FORMAT + " file (*." + Globals.CONVEYOR_FILE_FORMAT +")";
					}
					public boolean accept(File f) {
						if (f != null) {
							if (f.isDirectory())
								return true;
							return f.getName().toLowerCase().endsWith(Globals.CONVEYOR_FILE_FORMAT);
						}
						return false;
					}
				});
		    
				Component parent = pluginParameter.userInterface.getMainFrame();
				if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
					MainManager.config.setProperty(DEF_LAST_ICONVEYOR_IMPORT_DIRECTORY, fileChooser.getCurrentDirectory().getAbsolutePath());
					MainManager.threadPool.submit(new Runnable() {
						public void run() {
							try {
								String fileName = fileChooser.getSelectedFile().getPath();
								File myTempDir = File.createTempFile("install", "dir");
								myTempDir.delete();
								myTempDir.mkdirs();
								Unzip unzip = new Unzip(fileName, myTempDir.getAbsolutePath());
								unzip.run();
								
								// load graphml and executors jar file
                                Map<String, Class<Node>> executors = new HashMap<String, Class<Node>>();
                                try {
                                    JarClassLoader classLoader = new JarClassLoader(myTempDir.getAbsolutePath() + File.separator + Globals.JAR_FILE_NAME_IN_ARCHIVE);
                                    for (String className : classLoader.getClasses()) {
                                        Class<?> clazz = classLoader.getClass(className);
                                        try {
                                            Class<Node> nodeClass = (Class<Node>)clazz;
                                            executors.put(className, nodeClass);
                                        } catch (Exception ex) {}
                                    }
                                } catch (Exception ex) {}
                                List<Integer> new_graph_id = CommandOpener.openFile(myTempDir.getAbsolutePath() + File.separator + Globals.GRAPHML_FILE_NAME_IN_ARCHIVE, pluginParameter.model);

								// print debug
								MainManager.log.printDebug("[" + this.getClass().getName() + "] [OK] Open file = " + fileChooser.getSelectedFile().getPath());
								if(new_graph_id == null || new_graph_id.isEmpty()) {
									MainManager.windowMessage.errorMessage("Can't open file. May be file is empty", "Error");														
								} else {
									for(Integer buf : new_graph_id) {
                                        GraphModelHeader gh = pluginParameter.model.getGraphModelHeader(buf);
										if(gh != null) {
											conveyorPlugin.addNewGraphModel2ExecutorsPath(gh, myTempDir.getAbsolutePath() + File.separator + Globals.JAR_FILE_NAME_IN_ARCHIVE);
											conveyorPlugin.addNewGraphModel2ExecutorClasses(gh, executors);
											
											UIEventOpenNewGraph ong = new UIEventOpenNewGraph(buf, gh.name);
											pluginParameter.userInterface.addEvent(ong);
										} else {
											MainManager.windowMessage.errorMessage("Can't open file. Database error", "Error");
										}							
									}
								}
							} catch (Throwable e) {
								MainManager.windowMessage.showExceptionMessage(new Exception("Can't open file.\nException : " + e.getMessage()));
							}
						}
					});
				}
			}
		});
		
		pluginParameter.userInterface.addMenuItem(new AMenuItem(importIConveyorMenuItem) {
			public void update(Observable o, Object arg) {}
		}, "Import");				
	}
}
